﻿/*引用*/
/*引用不是定义一个新的变量，而是给已存在的变量取一个别名，编译器不会为引用变量开辟空间，它俩指向同一块空间*/

#include"cpp引用.h"
void test01() {
	//引用是指变量的另一个别名，
	//引用不会开辟新的内存空间，它和被引用变量指向同一块空间
	int a = 1;
	int& b = a;//引用变量必须初始化一个值
	b = 2;
	int& c = b;
	//我们甚至可以为别名再取别名
	std::cout << "b:" << b << ' ' << "a:" << a<<std::endl;
	//输出结果为b:2 a:2即改变引用变量可以改变被引用变量
	std::cout << "&b:" << &b <<std::endl<< "&a:" << &a<<std::endl<<"&c:"<<&c;
	//输出的地址一样
}
//引用的特点：1，引用变量必须初始化 2，一个变量可以有多个引用 3，引用一旦引用一个实体，则不能再引用其他实体

//引用的使用：1，引⽤在实践中主要是用于引⽤传参和引⽤做返回值中减少拷⻉提⾼效率和改变引⽤对象时同时改变被引⽤对象。
//			  2，引⽤传参跟指针传参功能是类似的，引⽤传参相对更⽅便⼀些。
void swap(int& x,int& y) {
	//与以往的传地址不同，这里的x,y直接就是a和b。
	int tmp = x;
	x = y;
	y = tmp;
}

void test02() {
	int a = 2;
	int b = 3;
	std::cout << "交换前a:" << a << " b:" << b << std::endl;
	swap(a, b);
	std::cout << "交换后a:" << a << " b:" << b << std::endl;
	ST stack;
	STInit(stack, 4);
	STPush(stack, 1);
	STPush(stack, 4);
	STPush(stack, 3);
	STPush(stack, 2);
	std::cout << STTop(stack) << std::endl;
	STTop(stack) += 1;//标记处
	std::cout << STTop(stack) << std::endl;
	/*
	int& STTop(ST& rs){
		assert(rs.top > 0);
		return rs.a[rs.top-1];
	}
	此处STTOP函数的返回值是一个引用值，
	若返回一个正常的int值，则标记处会报错，
	因为正常的int返回值不是直接返回，而是会把要返回的值临时再储存一下，
	返回储存的那个值，这样的值具有常性，无法进行++等操作。
	而返回一个引用值则不会出现上述情况
	*/
} 
void test03() {
	//const引用可以引用一个const变量
	const int a = 0;
	const int& b = a;
	//const引用也可以引用普通对象
	int c = 0;
	const int& d = c;
	//由此引出一个概念：由普通到const限制，属于权限缩小，
	//而在C++中，权限缩小是被允许的，相反权限扩大是不被允许的
	int f = 10;
	const int& rf = f * 3;
	double h = 2.2;
	const int& rh = h;
	//在C++中，以上的转换都遵循一个相似的原理，就是a*3和b的强转都会有
	//一个临时的对象储存中间值，而临时对象具有常性，需要使用const,否则会出现权限放大，编译错误
}
inline int Add(int a, int b) {
	return a + b;
}//inline修饰的函数称为内联函数，而C++编译器会把调用inline的函数展开，避免建立栈帧提高效率。
 //inline只是建议，编译器会根据不同的情况来确定是否展开。inline适用于短小而频繁调用的函数，
 //对于递归和代码较大的函数，则不会展开
 //C++inline的设计就是为了代替宏
 //debug版本默认不展开
 //inline不建议定义和声明分别建在两个文件中，会展开报错


/*nullptr
C++中NULL可能被定义为字⾯常量0，或者C中被定义为⽆类型指针(void*)的常量。不论采取何种
定义，在使⽤空值的指针时，都不可避免的会遇到⼀些⿇烦，本想通过f(NULL)调⽤指针版本的
f(int*)函数，但是由于NULL被定义成0，调⽤了f(int x)，因此与程序的初衷相悖。f((void*)NULL);
调⽤会报错。
• C++11中引⼊nullptr，nullptr是⼀个特殊的关键字，nullptr是⼀种特殊类型的字⾯量，它可以转换
成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题，因为nullptr只能被
隐式地转换为指针类型，⽽不能被转换为整数类型。*/
int main() {
	//test01();
	//test02();
	//test03();
	return 0;
}